let executeCount = 0;
const targetFn = async nums => {
  executeCount++;
  console.log( nums.map(num => 2 * num + 1))
  return nums.map(num => 2 * num + 1);
};

const batcher = (fn) => {
  // todo batch logic
  let allArgs = []
  // 能够实现 batch 的关键所在
  // 此处 fn(allArgs) 甚至可以实现为 fn([...new Set(allArgs)])，性能更好一些
  const wait = Promise.resolve().then(() => fn(allArgs))

  return async (args) => {
    allArgs = [...allArgs, ...args]
    const result = await wait

    // allArgs 与 result 形成的一个 Map
    // 借助于 lodash 可以更可读化地写成 Object.fromEntries(_.zip(allArgs, result))
    const resultMap = result.reduce((acc, x, i) => {
      const v = allArgs[i]
      acc[v] = x
      return acc
    }, {})
    return args.map(a => resultMap[a])
  }
}

const batchedFn = batcher(targetFn);

const main = async () => {
  const [result1, result2, result3] = await Promise.all([
    batchedFn([1, 2, 3]),
    batchedFn([4, 5]),
    batchedFn([6, 7]),
  ]);
  
  console.log(result1, result2, result3) 
  console.log(executeCount)  // 预期为 1
}

main()